package com.JUC.cha10.sec02;

import java.lang.ref.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

class MyObject {
    //这个方法一把不用复写
    @Override
    protected void finalize() throws Throwable {
        //finalize的通常目的是在对象被不可撤销地丢弃之前执行清理操作
        System.out.println("---------");
    }
}

public class ThreadLocalDemo {

    public static void main(String[] args) {
        MyObject myObject = new MyObject();
        ReferenceQueue<MyObject> referenceQueue = new ReferenceQueue<>();
        PhantomReference<MyObject> phantomReference = new PhantomReference<>(myObject, referenceQueue);

//        System.out.println(phantomReference.get());
        List<byte[]> list = new ArrayList<>();

        new Thread(() -> {
            while (true) {
                list.add(new byte[1 * 1024 * 1024]);
                // 暂停几秒钟线程
                try {
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(phantomReference.get() + "\t" + "list add OK");
            }
        }, "A").start();

        new Thread(() -> {
            while (true) {
                Reference<? extends MyObject> reference = referenceQueue.poll();
                if (reference != null) {
                    System.out.println("有虚对象回收加入了队列");
                    break;
                }
            }
        }, "B").start();
    }

    /**
     * 弱引用
     */
    private static void weakReference() {
        WeakReference<MyObject> weakReference = new WeakReference<>(new MyObject());
        System.out.println("gc before：" + "\t" + weakReference.get());

        System.gc();

        // 暂停几秒钟线程
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("gc after：" + "\t" + weakReference.get());
    }

    /**
     * 软引用
     */
    private static void softReference() {
        SoftReference<MyObject> softReference = new SoftReference<>(new MyObject());
//        System.out.println(softReference.get());

        System.gc();
        System.out.println("gc after And 内存充足：" + softReference.get());

        // 暂停几秒钟线程
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        try {
            byte[] bytes = new byte[20 * 1024 * 1024];//20MB对象
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            System.out.println("gc after And 内存不足：" + softReference.get());
        }
    }

    /**
     * 强引用
     */
    private static void strongReference() {
        MyObject myObject = new MyObject();
        System.out.println(Thread.currentThread().getName() + "\t" + myObject);

        myObject = null;

        System.gc();//人工开启GC，一般不用

        // 暂停几秒钟线程
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "\t" + myObject);
    }
}
